#include <QPainter>
#include <QThread>
#include <QMutex>
#include "rviz_custom_plugins/av_codec/video_decoder.h"

extern "C" {
#include <libavutil/dict.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}

namespace rviz_custom_plugins
{

namespace av_codec {

VideoDecoder::VideoDecoder(QObject *parent) : QThread(parent) {
    avformat_network_init();
}

VideoDecoder::~VideoDecoder() {
    stop();
    avformat_network_deinit();
}

bool VideoDecoder::startPlay(const QString &url) {
    m_url = url;
    m_paused = false;
    if (!isRunning()) {
        start();
    }
    return true;
}

void VideoDecoder::stop() {
    m_running = false;
    wait();
    // cleanup();
}

void VideoDecoder::pause() {
    m_paused = true;
}

void VideoDecoder::resume() {
    m_paused = false;
    m_pauseCond.wakeAll();
}

void VideoDecoder::run() {
    AVFormatContext *formatCtx = nullptr;
    AVCodecContext *codecCtx = nullptr;
    SwsContext *swsCtx = nullptr;
    int videoStream = -1;

    // 1. 打开RTSP流
    AVDictionary *options = nullptr;
    av_dict_set(&options, "rtsp_transport", "tcp", 0);
    av_dict_set(&options, "buffer_size", "102400", 0);
    av_dict_set(&options, "stimeout", "3000000", 0);

    if (avformat_open_input(&formatCtx, m_url.toUtf8().constData(), nullptr, &options) != 0) {
        emit error("Failed to open RTSP stream");
        return;
    }

    // 2. 查找视频流
    if (avformat_find_stream_info(formatCtx, nullptr) < 0) {
        emit error("Failed to find stream info");
        avformat_close_input(&formatCtx);
        return;
    }

    for (unsigned i = 0; i < formatCtx->nb_streams; i++) {
        if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStream = i;
            break;
        }
    }

    if (videoStream == -1) {
        emit error("No video stream found");
        avformat_close_input(&formatCtx);
        return;
    }

    // 3. 初始化解码器
    AVCodecParameters *codecPar = formatCtx->streams[videoStream]->codecpar;
    // 根据编码类型选择解码器
    const AVCodec *codec = avcodec_find_decoder(codecPar->codec_id);
    if (!codec) {
        emit error("Unsupported codec");
        avformat_close_input(&formatCtx);
        return;
    }

    codecCtx = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(codecCtx, codecPar);

    if (avcodec_open2(codecCtx, codec, nullptr) < 0) {
        emit error("Failed to open codec");
        avformat_close_input(&formatCtx);
        avcodec_free_context(&codecCtx);
        return;
    }

    // 4. 准备图像转换
    AVFrame *frame = av_frame_alloc();
    AVFrame *rgbFrame = av_frame_alloc();
    uint8_t *rgbBuffer = (uint8_t *)av_malloc(
        av_image_get_buffer_size(AV_PIX_FMT_RGB32, codecCtx->width, codecCtx->height, 1));
    av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, rgbBuffer,
                         AV_PIX_FMT_RGB32, codecCtx->width, codecCtx->height, 1);

    swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
                            codecCtx->width, codecCtx->height, AV_PIX_FMT_RGB32,
                            SWS_BILINEAR, nullptr, nullptr, nullptr);

    // 5. 主解码循环
    AVPacket *pkt = av_packet_alloc();
    m_running = true;

    while (m_running) {
        // 暂停处理
        m_mutex.lock();
        while (m_paused && m_running) {
            m_pauseCond.wait(&m_mutex);
        }
        m_mutex.unlock();

        if (!m_running) break;

        if (av_read_frame(formatCtx, pkt) < 0) {
            QThread::msleep(1);
            continue;
        }

        if (pkt->stream_index == videoStream) {
            if (avcodec_send_packet(codecCtx, pkt) == 0) {
                while (avcodec_receive_frame(codecCtx, frame) == 0) {
                    // 转换为RGB格式
                    sws_scale(swsCtx, frame->data, frame->linesize, 0,
                              frame->height, rgbFrame->data, rgbFrame->linesize);

                    // 创建QImage并发送
                    QImage img(rgbBuffer, codecCtx->width, codecCtx->height,
                               rgbFrame->linesize[0], QImage::Format_RGB32);
                    emit frameReady(img.copy());
                }
            }
        }
        av_packet_unref(pkt);
    }

    // 6. 清理资源
    av_frame_free(&frame);
    av_frame_free(&rgbFrame);
    av_free(rgbBuffer);
    av_packet_free(&pkt);
    avcodec_free_context(&codecCtx);
    avformat_close_input(&formatCtx);
    if (swsCtx) {
        sws_freeContext(swsCtx);
    }
}


}


}
